package com.glorious.security.extension.wechat;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import cn.hutool.core.bean.BeanUtil;
import com.glorious.api.AppUserFeignClient;
import com.glorious.common.Result;
import com.glorious.common.ResultCode;
import com.glorious.config.WxMaConfiguration;
import com.glorious.constant.GlobalConstants;
import com.glorious.dto.response.appuser.AppUserAuthResponse;
import com.glorious.entities.AppUser;
import com.glorious.security.core.userdetails.user.AppUserDetailsServiceImpl;
import lombok.Data;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;

import java.util.HashSet;

/**
 * 微信认证提供者
 */
@Data
public class WechatAuthenticationProvider implements AuthenticationProvider {

    private UserDetailsService userDetailsService;
//    private WxMaService wxMaService;
    private AppUserFeignClient appUserFeignClient;

    /**
     * 微信认证
     *
     * @param authentication
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        WechatAuthenticationToken authenticationToken = (WechatAuthenticationToken) authentication;
        String code = (String) authenticationToken.getPrincipal();
        String appid = authenticationToken.getAppid();

        WxMaJscode2SessionResult sessionInfo = null;
        WxMaService wxMaService = WxMaConfiguration.getMaService(appid);
        try {
            sessionInfo = wxMaService.getUserService().getSessionInfo(code);
        } catch (WxErrorException e) {
            e.printStackTrace();
        }

        String openid = sessionInfo.getOpenid();
        String sessionKey = sessionInfo.getSessionKey();
        String unionId = sessionInfo.getUnionid();

        Result<AppUserAuthResponse> appUserAuthResponse = appUserFeignClient.loadUserByOpenId(openid);
        // 微信用户不存在，注册成为新会员
        if (appUserAuthResponse != null && ResultCode.USER_NOT_EXIST.getCode().equals(appUserAuthResponse.getCode())) {
            AppUser appUser = new AppUser();
            appUser.setOpenId(openid);
            appUser.setAppid(appid);
            appUser.setSessionKey(sessionKey);
            appUser.setUnionId(unionId);
            appUser.setStatus(GlobalConstants.STATUS_YES);

            String encryptedData = authenticationToken.getEncryptedData();
            String iv = authenticationToken.getIv();
            if (StringUtils.isNotBlank(encryptedData) && StringUtils.isNotBlank(iv)) {
                // 解密 encryptedData 获取用户信息
                WxMaUserInfo userInfo = wxMaService.getUserService().getUserInfo(sessionKey, encryptedData, iv);
                BeanUtil.copyProperties(userInfo, appUser);
            }

            appUserFeignClient.add(appUser);
        }
        UserDetails userDetails = ((AppUserDetailsServiceImpl) userDetailsService).loadUserByOpenId(openid);
        WechatAuthenticationToken result = new WechatAuthenticationToken(userDetails, new HashSet<>());
        result.setDetails(authentication.getDetails());
        return result;
    }


    @Override
    public boolean supports(Class<?> authentication) {
        return WechatAuthenticationToken.class.isAssignableFrom(authentication);
    }
}
